package com.shopnight.service.impl;


import  com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shopnight.entity.Image;
import com.shopnight.entity.ShopOrder;
import com.shopnight.entity.Stock;
import com.shopnight.mapper.ShopOrderMapper;
import com.shopnight.service.CartService;
import com.shopnight.service.IImageService;
import com.shopnight.service.ShopOrderService;
import com.shopnight.service.StockService;
import com.shopnight.redisEntity.Cart;
import com.shopnight.redisEntity.CartItem;
import com.shopnight.redisEntity.CheckItemVo;
import com.shopnight.utils.UserContext;
import com.shopnight.vo.GoodsOrderVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ExecutionException;


@Slf4j
@Service
public class CarServiceImpl implements CartService {
    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    private StockService stockService;
    private final String CART_PREFIX="cart";

    @Autowired
    private ShopOrderService shopOrderService;
    @Autowired
    private IImageService iImageService;
    @Autowired
    private ShopOrderMapper shopOrderMapper;

    /**
     * 绑定角色购物车
     * 获取到购物车
     * @return
     */
    private BoundHashOperations<String, Object, Object> getCartOps() {
        String cartKey = CART_PREFIX+ ":" + UserContext.getEndUserId();
        BoundHashOperations<String, Object, Object> stringObjectObjectBoundHashOperations = redisTemplate.boundHashOps(cartKey);
        return stringObjectObjectBoundHashOperations;
    }

    /**
     * 添加购物车
     * @param orderId
     * @param num
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Override
    public CartItem addToCart(Long orderId, Integer num)  {
        //获取购物车
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        //购物车是否存该商品
        String res = (String) cartOps.get(orderId.toString());
        if (StringUtils.isEmpty(res)){
            //购物车无此商品
            CartItem cartItem = new CartItem();
            ShopOrder shopOrder = shopOrderService.getById(orderId);
            String s = JSON.toJSONString(shopOrder);
            GoodsOrderVo goodsOrderVo = JSON.parseObject(s, new TypeReference<GoodsOrderVo>() {});

            //2、商品添加到购物车
            cartItem.setCheck(true);
            cartItem.setOrderNum(num);
            cartItem.setPriceDiscounts(shopOrder.getPriceDiscounts());
            cartItem.setPriceSeckill(shopOrder.getPriceSeckill());
            cartItem.setSeckill(shopOrder.getSeckill() == 1 ? true : false);
            Image image = iImageService.getOne(new QueryWrapper<Image>().eq("order_id", orderId).eq("default_img", 1));
            cartItem.setImgUrl(image.getImgUrl());
            cartItem.setOrderName(goodsOrderVo.getOrderName());
            cartItem.setOrderId(orderId);
            cartItem.setPrice(goodsOrderVo.getPrice());
            Stock stock = stockService.getOne(new QueryWrapper<Stock>().eq("order_id", orderId));
            cartItem.setStockCount(stock.getStockCount());
            cartItem.setOrgId(shopOrder.getOrgId());   //设置商品的组织id
            cartItem.setCreateTime(new Date());
            String s1 = JSON.toJSONString(cartItem);
            cartOps.put(goodsOrderVo.getOrderId().toString(),s1);
            return cartItem;
        }else {
            //购物车有此商品，修改数量 更新时间
            CartItem cartItem = JSON.parseObject(res, CartItem.class);
            cartItem.setOrderNum(cartItem.getOrderNum()+num);
            cartOps.put(orderId.toString(),JSON.toJSONString(cartItem));
            return cartItem;
        }

    }

    @Override
    public CartItem getCartItem(Long orderId) {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        String s = (String) cartOps.get(orderId.toString());
        CartItem cartItem = JSON.parseObject(s, CartItem.class);
        return cartItem;
    }

    public List<CartItem> getCartItems(Long orgId){
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        List<Object> values = cartOps.values();
        if (values!=null && values.size()>0){

            ArrayList orderIds = new ArrayList();
            ArrayList<CartItem> cartItems = new ArrayList<>();
            ArrayList<CartItem> cartItems2 = new ArrayList<>();

            values.stream().map(obj->{
                String s = (String) obj;
                CartItem cartItem = JSON.parseObject(s, CartItem.class);
                return cartItem;
            }).sorted((item,item2)->{
                   return   item.getCreateTime().getTime() - item2.getCreateTime().getTime() > 0 ? 1 : -1;
            }).forEach(cartItem-> {
                if (cartItem.getOrgId().equals(orgId)) {
                    cartItems.add(cartItem);
                    orderIds.add(cartItem.getOrderId());
                }
            });

            if (cartItems.size() > 0 ){
                List<CartItem> dbCartItems = shopOrderMapper.getCartItem(orderIds);
                cartItems.forEach(cartItem->{
                    dbCartItems.forEach(dbCartItem->{
                        if (Objects.equals(cartItem.getOrderId(), dbCartItem.getOrderId())){
                            cartItem.setOrderName(dbCartItem.getOrderName());
                            cartItem.setSeckill(dbCartItem.getSeckill() ? true : false);
                            cartItem.setPriceDiscounts(dbCartItem.getPriceDiscounts());
                            cartItem.setPriceSeckill(dbCartItem.getPriceSeckill());
                            cartItem.setStockCount(dbCartItem.getStockCount());
                            BigDecimal subtract = cartItem.getPrice().subtract(dbCartItem.getPrice());
                            int j = subtract.compareTo(new BigDecimal(0));
                            cartItem.setPriceCut(j == 1 ? subtract : new BigDecimal(0));
                            cartItem.setPrice(dbCartItem.getPrice());
                            cartOps.put(cartItem.getOrderId().toString(), JSON.toJSONString(cartItem));
                            cartItems2.add(cartItem);
                        }
                    });
                });
            }

            return cartItems;
        }
        return null;
    }


    /**
     * 获取整个购物车
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Override
    public Cart getCart(Long orgId) {
        Cart cart = new Cart();
        List<CartItem> cartItems = getCartItems(orgId);
        cart.setItems(cartItems);
        return cart;
    }

    /**
     * 修改购物车选中状态
     */
    @Override
    public void checkItem(List<CheckItemVo> checkItemVos) {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        for (CheckItemVo checkItemVo:checkItemVos){
            CartItem cartItem = getCartItem(checkItemVo.getOrderId());
            cartItem.setCheck(checkItemVo.getIsCheck() == 1 ? true : false);
            String s = JSON.toJSONString(cartItem);
            cartOps.put(checkItemVo.getOrderId().toString(), s);
        }
    }

    /**
     * 修改购物项数量
     * @param orderId
     * @param num
     */
    @Override
    public void changeItemCount(Long orderId, Integer num) {
        CartItem cartItem = getCartItem(orderId);
        cartItem.setOrderNum(num);
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        cartOps.put(orderId.toString(),JSON.toJSONString(cartItem));
    }

    /**
     * 删除购物项
     * @param orderId
     */
    @Override
    public void deleteItem(Long orderId) {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        cartOps.delete(orderId.toString());
    }

    @Override
    public void deleteItems(Long[] orderIds) {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        for (Long order:orderIds){
            cartOps.delete(order.toString());
        }
    }

    @Override
    public void userIdByDelete(String userId){
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        redisTemplate.delete(CART_PREFIX+":"+userId);
    }


}
